#include "serialportmanager.h"
#include <QDebug>

/**
 * @brief 构造函数
 * @param parent 父对象指针
 */
SerialPortManager::SerialPortManager(QObject *parent)
    : QObject(parent)
    , m_serialPort(new QSerialPort(this))
    , m_refreshTimer(new QTimer(this))
    , m_baudRate(9600)
{
    // 连接串口信号
    connect(m_serialPort, &QSerialPort::readyRead, 
            this, &SerialPortManager::handleReadyRead);
    connect(m_serialPort, &QSerialPort::errorOccurred,
            this, &SerialPortManager::handleSerialError);

    // 设置刷新定时器
    m_refreshTimer->setInterval(2000); // 每2秒刷新一次
    connect(m_refreshTimer, &QTimer::timeout,
            this, &SerialPortManager::onRefreshTimer);
    m_refreshTimer->start();

    // 初始化串口列表
    updateAvailablePorts();
}

/**
 * @brief 析构函数
 */
SerialPortManager::~SerialPortManager()
{
    if (m_serialPort->isOpen()) {
        m_serialPort->close();
    }
}

/**
 * @brief 获取可用串口列表
 * @return 串口名称列表
 */
QStringList SerialPortManager::availablePorts() const
{
    return m_availablePorts;
}

/**
 * @brief 检查是否已连接
 * @return 连接状态
 */
bool SerialPortManager::isConnected() const
{
    return m_serialPort->isOpen();
}

/**
 * @brief 获取当前串口名称
 * @return 当前串口名称
 */
QString SerialPortManager::currentPort() const
{
    return m_currentPort;
}

/**
 * @brief 获取波特率
 * @return 当前波特率
 */
int SerialPortManager::baudRate() const
{
    return m_baudRate;
}

/**
 * @brief 设置波特率
 * @param rate 波特率值
 */
void SerialPortManager::setBaudRate(int rate)
{
    if (m_baudRate != rate) {
        m_baudRate = rate;
        
        // 如果串口已打开，需要重新配置
        if (m_serialPort->isOpen()) {
            m_serialPort->setBaudRate(rate);
        }
        
        emit baudRateChanged(rate);
    }
}

/**
 * @brief 连接到指定串口
 * @param portName 串口名称
 * @param baudRate 波特率 (默认9600)
 * @return 连接是否成功
 */
bool SerialPortManager::connectToPort(const QString &portName, int baudRate)
{
    // 如果已经连接，先断开
    if (m_serialPort->isOpen()) {
        disconnectPort();
    }

    // 设置串口参数
    m_serialPort->setPortName(portName);
    m_serialPort->setBaudRate(baudRate);
    m_serialPort->setDataBits(QSerialPort::Data8);
    m_serialPort->setParity(QSerialPort::NoParity);
    m_serialPort->setStopBits(QSerialPort::OneStop);
    m_serialPort->setFlowControl(QSerialPort::NoFlowControl);

    // 尝试打开串口
    if (m_serialPort->open(QIODevice::ReadWrite)) {
        m_currentPort = portName;
        m_baudRate = baudRate;
        
        qDebug() << "成功连接到串口:" << portName << "波特率:" << baudRate;
        
        emit connectionStatusChanged(true);
        emit currentPortChanged(portName);
        emit baudRateChanged(baudRate);
        
        return true;
    } else {
        QString errorMsg = QString("无法打开串口 %1: %2")
                          .arg(portName)
                          .arg(m_serialPort->errorString());
        
        qDebug() << errorMsg;
        emit errorOccurred(errorMsg);
        
        return false;
    }
}

/**
 * @brief 断开串口连接
 */
void SerialPortManager::disconnectPort()
{
    if (m_serialPort->isOpen()) {
        m_serialPort->close();
        m_currentPort.clear();
        m_receiveBuffer.clear();
        
        qDebug() << "串口连接已断开";
        
        emit connectionStatusChanged(false);
        emit currentPortChanged(QString());
    }
}

/**
 * @brief 刷新可用串口列表
 */
void SerialPortManager::refreshPorts()
{
    updateAvailablePorts();
}

/**
 * @brief 发送数据到串口
 * @param data 要发送的数据
 * @return 发送的字节数
 */
qint64 SerialPortManager::sendData(const QByteArray &data)
{
    if (!m_serialPort->isOpen()) {
        emit errorOccurred("串口未连接");
        return -1;
    }

    qint64 bytesWritten = m_serialPort->write(data);
    if (bytesWritten == -1) {
        emit errorOccurred("数据发送失败: " + m_serialPort->errorString());
    } else {
        qDebug() << "发送数据:" << data.size() << "字节";
    }

    return bytesWritten;
}

/**
 * @brief 处理串口数据接收
 */
void SerialPortManager::handleReadyRead()
{
    QByteArray data = m_serialPort->readAll();
    if (!data.isEmpty()) {
        m_receiveBuffer.append(data);
        emit dataReceived(data);
        
        // 处理接收缓冲区中的完整行
        processReceiveBuffer();
    }
}

/**
 * @brief 处理串口错误
 * @param error 串口错误类型
 */
void SerialPortManager::handleSerialError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::ResourceError) {
        // 设备被移除或连接丢失
        QString errorMsg = "串口连接丢失: " + m_serialPort->errorString();
        qDebug() << errorMsg;
        
        disconnectPort();
        emit errorOccurred(errorMsg);
    } else if (error != QSerialPort::NoError) {
        QString errorMsg = "串口错误: " + m_serialPort->errorString();
        qDebug() << errorMsg;
        emit errorOccurred(errorMsg);
    }
}

/**
 * @brief 定时刷新串口列表
 */
void SerialPortManager::onRefreshTimer()
{
    updateAvailablePorts();
}

/**
 * @brief 更新可用串口列表
 */
void SerialPortManager::updateAvailablePorts()
{
    QStringList newPorts;
    
    // 获取所有可用串口
    const auto serialPortInfos = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo &portInfo : serialPortInfos) {
        QString portName = portInfo.portName();
        QString description = portInfo.description();
        
        // 组合显示名称和描述
        if (!description.isEmpty() && description != portName) {
            newPorts << QString("%1 (%2)").arg(portName, description);
        } else {
            newPorts << portName;
        }
    }

    // 检查列表是否有变化
    if (newPorts != m_availablePorts) {
        m_availablePorts = newPorts;
        emit availablePortsChanged();
        
        qDebug() << "可用串口列表已更新:" << m_availablePorts;
    }
}

/**
 * @brief 处理接收缓冲区中的数据
 */
void SerialPortManager::processReceiveBuffer()
{
    while (m_receiveBuffer.contains('\n')) {
        int lineEndIndex = m_receiveBuffer.indexOf('\n');
        QByteArray lineData = m_receiveBuffer.left(lineEndIndex);
        m_receiveBuffer.remove(0, lineEndIndex + 1);
        
        // 移除回车符
        if (lineData.endsWith('\r')) {
            lineData.chop(1);
        }
        
        QString line = QString::fromLatin1(lineData);
        if (!line.isEmpty()) {
            emit lineReceived(line);
        }
    }
    
    // 防止缓冲区过大
    if (m_receiveBuffer.size() > 4096) {
        m_receiveBuffer.clear();
        emit errorOccurred("接收缓冲区溢出，已清空");
    }
}